package com.ihemou.common.security.config;

import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.filter.SaServletFilter;
import cn.dev33.satoken.id.SaIdUtil;
import cn.dev33.satoken.interceptor.SaAnnotationInterceptor;
import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
import com.ihemou.common.core.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.Arrays;

/**
 * @author saperliu
 * @version 1.0.0
 * @date 2021-08-30 11:48
 * @Description 网关访问，带有id-token,每个微服务检验id-token
 */
@Configuration
public class IdTokenConfigure implements WebMvcConfigurer {

    private static final Logger log = LoggerFactory.getLogger(IdTokenConfigure.class);

    @Autowired
    IgnoreWhitePath ignoreWhitePath;

    /**
     * 全局过滤器，校验是否从网关过来的访问，否则拒绝
     *
     * @return
     */
    @Bean
    public SaServletFilter getSaServletFilter() {
        return new SaServletFilter()
                .addInclude("/**")
                .setAuth(r -> {
                    // 校验 Id-Token 身份凭证     —— 以下两句代码可简化为：SaIdUtil.checkCurrentRequestToken();
                    String token = SaHolder.getRequest().getHeader(SaIdUtil.ID_TOKEN);
                    log.info("------------IdTokenConfigure--------{} {}", token, ignoreWhitePath.getWhites());
                    // 通过网关的请求验证id_token
                    if(StringUtils.isNotEmpty(token)){
                        SaIdUtil.checkToken(token);
                    }else{
                        // 不通过网关的请求,验证登录
                        SaRouter.match(Arrays.asList("/**"),ignoreWhitePath.getWhites(),() -> StpUtil.checkLogin());
                    }
                })
                .setError(e -> {
                    return SaResult.error(e.getMessage());
                });
    }
    // 注册Sa-Token的注解拦截器，打开注解式鉴权功能
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 注册注解拦截器，并排除不需要注解鉴权的接口地址 (与登录拦截器无关)
        registry.addInterceptor(new SaAnnotationInterceptor()).addPathPatterns("/**");
    }

}
